/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jus.aor.mobilagent.kernel;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import jus.aor.mobilagent.loader.BAMLoader;

/**
 *
 * @author thomas
 */
public class AgentServer extends Thread implements AgentServerInterface {

    private ServerSocket serverSocket;
    private int port;
    private BAMLoader loader;
    private String name;
    private Map<String, ServiceInterface> services = new HashMap<String, ServiceInterface>();

    public AgentServer(int port, String name, BAMLoader loader) {
        super(name);
        this.port = port;
        this.loader = loader;
    }

    public void addService(String name, ServiceInterface service) {
        services.put(name, service);
    }

    @Override
    public void run() {
        try {
            Thread.currentThread().setContextClassLoader(loader);
            serverSocket = new ServerSocket(port);
            while (true) {
                final Socket s = serverSocket.accept();

                try {
                    final BAMLoader agentLoader = new BAMLoader(Thread.currentThread().getContextClassLoader());

                    AgentInputStream ais = new AgentInputStream(s.getInputStream(), agentLoader);

                    Jar j = (Jar) ais.readObject();

                    agentLoader.addJar(j);
                    final AgentInterface agent = (AgentInterface) ais.readObject();
                    agent.setClasses(j);

                    agent.init(agentLoader, this, name);
                    new Thread(agent).start();

                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(AgentServer.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    s.close();
                }

            }
        } catch (IOException ex) {
            Logger.getLogger(AgentServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void startAgent(final AgentInterface agent, final BAMLoader agentLoader) {
        System.out.println("Demarrage d'un agent");
        agent.init(agentLoader, this, name);
        new Thread(agent).start();
    }

    @Override
    public URI getUri() {
        try {
            return new URI("mobilagent://" + InetAddress.getLocalHost().getHostAddress() + ":" + port);

        } catch (URISyntaxException | UnknownHostException ex) {
            Logger.getLogger(AgentServer.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    @Override
    public ServiceInterface getService(String serviceName) {
//        return services.get(serviceName);
        return null;
    }

    @Override
    public void sendAgentTo(AgentInterface agent, URI destination) {
        System.out.println("sendAgent to " + destination);
        try {
            Socket s = new Socket(destination.getHost(), destination.getPort());
            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());

            oos.writeObject(agent.getClasses());

            oos.writeObject(agent);

            oos.close();
            s.close();

        } catch (UnknownHostException ex) {
            Logger.getLogger(AgentServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(AgentServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
